﻿using System.Collections.Generic;
using System.Linq;

namespace DiscreteMath
{
	public class TransitionDictionary : IDictionary<Configuration, ISet<State>>
	{
		private IDictionary<Configuration, ISet<State>> transitions;

		public TransitionDictionary()
		{
			this.transitions = new Dictionary<Configuration, ISet<State>>();
		}

		public TransitionDictionary(IDictionary<Configuration, ISet<State>> dictionary)
		{
			this.transitions = 
                new Dictionary<Configuration, ISet<State>>(dictionary.ToDictionary(x => x.Key, y => new HashSet<State>(y.Value) as ISet<State>));
		}

        public int Count
        {
            get { return this.transitions.Count; }
        }

        public bool IsReadOnly
        {
            get { return this.transitions.IsReadOnly; }
        }

        public ICollection<Configuration> Keys
        {
            get { return this.transitions.Keys; }
        }

        public ICollection<ISet<State>> Values
        {
            get { return this.transitions.Values; }
        }

        public ISet<State> this[Configuration key]
        {
            get
            {
                if (this.transitions.ContainsKey(key))
                    return this.transitions[key];

                return EmptySet<State>.Empty;
            }
            set
            {
                this.transitions[key] = value;
            }
        }

        public ISet<State> this[State state, char letter]
        {
            get
            {
                return this[new Configuration(state, letter)];
            }
            set
            {
                this[new Configuration(state, letter)] = value;
            }
        }

		public void Add(Configuration key, ISet<State> value)
		{
			if (this.transitions.ContainsKey(key))
			{
				this.transitions[key].UnionWith(value);
			}
			else
			{
				this.transitions.Add(key, value);
			}
		}

        public void Add(State state, char letter, ISet<State> value)
        {
            this.Add(new Configuration(state, letter), value);
        }

		public bool ContainsKey(Configuration key)
		{
			return this.transitions.ContainsKey(key);
		}

		public bool TryGetValue(Configuration key, out ISet<State> value)
		{
			return this.transitions.TryGetValue(key, out value);
		}

		public void Add(KeyValuePair<Configuration, ISet<State>> item)
		{
			this.transitions.Add(item);
		}

		public void Clear()
		{
			this.transitions.Clear();
		}

		public bool Contains(KeyValuePair<Configuration, ISet<State>> item)
		{
			return this.transitions.Contains(item);
		}

		public void CopyTo(KeyValuePair<Configuration, ISet<State>>[] array, int arrayIndex)
		{
			this.transitions.CopyTo(array, arrayIndex);
		}

		public bool Remove(KeyValuePair<Configuration, ISet<State>> item)
		{
			return this.transitions.Remove(item);
		}

        public bool Remove(Configuration key)
        {
            return this.transitions.Remove(key);
        }

		public IEnumerator<KeyValuePair<Configuration, ISet<State>>> GetEnumerator()
		{
			return this.transitions.GetEnumerator();
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return this.transitions.GetEnumerator();
		}
    }
}
